import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.LockSupport;

public class fairLock {

    private final AtomicBoolean flag = new AtomicBoolean(false);
    //记录持有锁的线程
    private volatile Thread owner = null;

    //线程安全的头节点
    private final AtomicReference<Node> head = new AtomicReference<>(new Node());

    private final AtomicReference<Node> tail = new AtomicReference<>(head.get());

    void lock(){
        //为实现公平锁，必须按照链表顺序来,不许依赖就抢锁
        /*
        if(flag.compareAndSet(false, true)){
            owner = Thread.currentThread();
            System.out.println(Thread.currentThread().getName() + " 获取锁");
        }
        * */
        Node current = new Node();
        current.thread = Thread.currentThread();

        while(true){
            //获取最新尾节点
            Node currentTail = this.tail.get();
            if(this.tail.compareAndSet(currentTail, current)){//如果当前为节点是尾节点，则加入尾部
                System.out.println(Thread.currentThread().getName() + " 加入了链表尾部");
                currentTail.next = current;
                current.prev = currentTail;
                break;
            }
        }
        while(true){
            if(current.prev == head.get() && flag.compareAndSet(false,  true)){
                this.owner = Thread.currentThread();
                head.set(current);
                current.prev.next = null;
                current.prev = null;
                System.out.println(Thread.currentThread().getName() + " 被唤醒之后获取锁");
                return;
            }
            // 阻塞线程
            LockSupport.park();
        }


    }


    //释放锁
    void unlock(){
        if(Thread.currentThread() != this.owner){
            throw new RuntimeException("当前线程并没有锁，不能解锁" + Thread.currentThread().getName() + ",owner: " + owner.getName());
        }
        Node headNode = this.head.get();
        Node next = headNode.next;
        flag.set(false);
        if(next != null){
            LockSupport.unpark(next.thread);
        }
    }

    static class Node{
        volatile Thread thread;
        volatile Node next;
        volatile Node prev;
    }
}
